package com.shanshan.wheel.rpc.common.serialize;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.shanshan.wheel.rpc.common.remoting.dto.RpcRequest;
import com.shanshan.wheel.rpc.common.remoting.dto.RpcResponse;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @Description Kryo 序列化反序列化器实现类
 * @ClassName KryoSerializer
 * @Author 山山大魔王
 * @Date 2022/9/4 21:04
 * @Version 1.0
 */
public class KryoSerializer implements Serializer {
    //Kryo是非线程安全的，使用ThreadLocal为每个线程配置一个Kryo，互不干扰
    private final ThreadLocal<Kryo> kryoThreadLocal = ThreadLocal.withInitial(()->{
        Kryo kryo = new Kryo();
        kryo.register(RpcRequest.class);
        kryo.register(RpcResponse.class);
        return kryo;
    });


    @Override
    public byte[] serialize(Object object) {
        try(/*在此处定义，自动关闭资源*/
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                Output output = new Output(out)
        ){

            Kryo kryo = kryoThreadLocal.get();
            kryo.writeObject(output, object);
            return output.toBytes();
        } catch (IOException e) {
            throw  new RuntimeException("序列化失败！！");
        }catch (Exception e){
            throw e;
        }
        //java.lang.IllegalArgumentException: Class is not registered: java.lang.Class[]
        //Note: To register this class use: kryo.register(java.lang.Class[].class);
    }

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {

        try(/*在此处定义，自动关闭资源*/ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        Input input = new Input(in)) {
            Kryo kryo = kryoThreadLocal.get();
            return kryo.readObject(input, clazz);
        } catch (IOException e) {
            throw new RuntimeException("反序列化失败！！");
        }

    }

}
